﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using System.ComponentModel.DataAnnotations;

namespace EcoSystem
{
    /// <summary>
    /// 报表配置接口实现
    /// </summary>
    public class ReportCategoryConfigAppService : CrudAppService<
         ReportCategoryConfig,
         ReportCategoryConfigDto,
         Guid,
         GetReportCategoryConfigInput,
         CreateOrUpdateReportCategoryConfigDto,
         CreateOrUpdateReportCategoryConfigDto>, IReportCategoryConfigAppService
    {
        private readonly IRepository<HttpApiConfig, Guid> apiRepository;
        private readonly IRepository<ReportConfig, Guid> reportRepository;

        public ReportCategoryConfigAppService(
            IRepository<ReportCategoryConfig, Guid> repository,
            IRepository<HttpApiConfig, Guid> apiRepository,
            IRepository<ReportConfig, Guid> reportRepository)
            : base(repository)
        {
            this.apiRepository = apiRepository;
            this.reportRepository = reportRepository;
        }

        public override async Task<ReportCategoryConfigDto> GetAsync(Guid id)
        {
            var result = await (await Repository.GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id);
            return MapToGetOutputDto(result);
        }

        /// <summary>
        /// 创建报表配置
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        public override async Task<ReportCategoryConfigDto> CreateAsync(CreateOrUpdateReportCategoryConfigDto input)
        {
            if (string.IsNullOrEmpty(input.Name))
            {
                throw new UserFriendlyException("名称不能为空!");
            }
            return await base.CreateAsync(input);
        }

        /// <summary>
        /// 更新报表配置
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        public override async Task<ReportCategoryConfigDto> UpdateAsync(Guid id, CreateOrUpdateReportCategoryConfigDto input)
        {
            var report = await (await Repository.GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id);
            if (report == null)
            {
                throw new UserFriendlyException("要修改的分类信息不存在");
            }
            if (string.IsNullOrEmpty(input.Name))
            {
                throw new UserFriendlyException("名称不能为空!");

            }
            return await base.UpdateAsync(id, input);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async override Task<PagedResultDto<ReportCategoryConfigDto>> GetListAsync(GetReportCategoryConfigInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking();
            query = query.WhereIf(input.ParentId.HasValue, x => x.ParentId == input.ParentId)
              .WhereIf(input.Type.HasValue, x => x.Type == input.Type)
              .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var totalCount = await query.CountAsync();
            var list = await query.OrderByDescending(x => x.CreationTime).PageBy(input.SkipCount, input.MaxResultCount).ToListAsync();
            return new PagedResultDto<ReportCategoryConfigDto>()
            {
                TotalCount = totalCount,
                Items = ObjectMapper.Map<List<ReportCategoryConfig>, List<ReportCategoryConfigDto>>(list)
            };
        }

        public async Task<ListResultDto<ReportCategoryConfigDto>> GetAllAsync(GetReportCategoryConfigInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking();
            query = query.WhereIf(input.ParentId.HasValue, x => x.ParentId == input.ParentId)
                .WhereIf(input.Type.HasValue, x => x.Type == input.Type)
                .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var list = await query.ToListAsync();
            var items = ObjectMapper.Map<List<ReportCategoryConfig>, List<ReportCategoryConfigDto>>(list);
            return new ListResultDto<ReportCategoryConfigDto>() { Items = items };
        }

        public async Task<List<ReportCategoryConfigTreeDto>> GetTreeAsync(GetReportCategoryTreeInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking();
            query = query.Where(x => x.Type == input.Type)
                .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var list = await query.ToListAsync();
            var allItems = ObjectMapper.Map<List<ReportCategoryConfig>, List<ReportCategoryConfigDto>>(list);
            return CreateChildren(allItems, Guid.Empty);
        }

        /// <summary>
        /// 递归创建下级节点数据
        /// </summary>
        /// <param name="allItems"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private List<ReportCategoryConfigTreeDto> CreateChildren(List<ReportCategoryConfigDto> allItems, Guid parentId)
        {
            List<ReportCategoryConfigTreeDto> items = new List<ReportCategoryConfigTreeDto>();
            if (parentId == Guid.Empty)
            {
                items = allItems.Where(x => x.ParentId == Guid.Empty || x.ParentId == null)
                    .Select(x => new ReportCategoryConfigTreeDto(x)).ToList();
            }
            else
            {
                items = allItems.Where(x => x.ParentId == parentId)
                    .Select(x => new ReportCategoryConfigTreeDto(x)).ToList();
            }
            items.ForEach(item =>
            {
                var subItems = CreateChildren(allItems, item.Id);
                if (subItems.Count > 0)
                {
                    item.Children = subItems;
                }
                else
                {
                    item.Children = null;
                }
            });
            return items;
        }

        public override async Task DeleteAsync(Guid id)
        {
            var item = await (await Repository.GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id);
            if (item.Type == ReportCategoryTypeEnum.GeneralReport)
            {
                if (await reportRepository.AnyAsync(x => x.CategoryId == id))
                {
                    throw new UserFriendlyException("当前分类下已有对应的报表配置，请先移除报表配置后才能删除该分类");
                }
            }
            if (item.Type == ReportCategoryTypeEnum.HttpInterface)
            {
                if (await apiRepository.AnyAsync(x => x.CategoryId == id))
                {
                    throw new UserFriendlyException("当前分类下已有对应的API接口配置，请先移除API接口配置后才能删除该分类");
                }
            } 
            await base.DeleteAsync(id);
        }
    }
}
